﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SPMS.Commons.Configuration;
using SPMS.Log.Core;
using SPMS.Utility;

namespace SPMS.Log.Configuration.Handler
{
    /// <summary>
    /// 日志追加器节点处理器
    /// </summary>
    /// <remarks>用于处理日志追加器节点</remarks>
    /// <history>
    /// [zanezeng]               2009/10/15 14:13    创建
    /// </history>
    public sealed class Appender_NodeHandler : AbstractNodeHandler
    {
        /// <summary>
        /// 处理指定的节点
        /// </summary>
        /// <param name="node">配置节点</param>
        /// <param name="context">处理上下文</param>
        /// <returns>根据配置信息创建的对象</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]   2008-11-17 11:39    Created
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/15 14:14    创建
        /// </history>
        protected override object ProcessInternal(IConfigurationNode node, ParseContext context)
        {
            //输出日志
            if (LoggingContext.MetaLog.IsTraceEnabled)
            {
                LoggingContext.MetaLog.Trace("准备解析日志追加器");
            }

            //获得日志追加器的名称
            string appenderName = this.GetAttributeValue(node, LogConfiguationTags.ATTRIBUTE_NAME, context);

            //判断是否指定了追加器的名称
            if (string.IsNullOrEmpty(appenderName))
            {
                //抛出异常
                throw new ConfigurationException(string.Format(Properties.Resources.MSG_CONFIGURATION_ATTRIBUTE_REQUIRED, node.Name, LogConfiguationTags.ATTRIBUTE_NAME), node);
            }

            //判断指定的日志追加器是否已经存在
            if (null != context.Repository.GetAppender(appenderName))
            {
                //抛出异常
                throw new ConfigurationException(string.Format(Properties.Resources.MSG_CONFIGURATION_APPENDER_DUPLICATE, appenderName, context.Repository.Name), node);
            }

            //获得日志追加器的类型
            string typeName = this.GetAttributeValue(node, LogConfiguationTags.ATTRIBUTE_TYPE, context);

            //判断是否指定了追加器的类型
            if (string.IsNullOrEmpty(typeName))
            {
                //抛出异常
                throw new ConfigurationException(string.Format(Properties.Resources.MSG_CONFIGURATION_ATTRIBUTE_REQUIRED, node.Name, LogConfiguationTags.ATTRIBUTE_TYPE), node);
            }

            //获得日志追加器类型
            Type appenderType = Type.GetType(typeName);

            //创建日志追加器
            ILogAppender appender = (ILogAppender)Activator.CreateInstance(appenderType, new object[] { appenderName });

            //获得可用状态
            string isEnabled = this.GetAttributeValue(node, LogConfiguationTags.ATTRIBUTE_ENABLED, context);

            //判断是否设置了可用状态
            if (!string.IsNullOrEmpty(isEnabled))
            {
                //设置日志记录器的可用状态
                appender.IsEnabled = bool.Parse(isEnabled);
            }

            //用于保存配置节点处理器
            IConfigurationNodeHandler<ParseContext> handler;

            //用于保存处理的结果
            object instance = null;

            //用于保存属性
            PropertyValue property = null;

            //用于保存属性
            System.Reflection.PropertyInfo propertyInfo = null;

            //循环当前配置节点的所有子节点
            foreach (IConfigurationNode subNode in node.ChildNodes)
            {
                //获得配置节点处理器
                handler = context.GetNodeHandler(subNode);

                //判断是否为Null
                if (null == handler)
                {
                    //抛出异常
                    throw new NotSupportedException(string.Format(Properties.Resources.MSG_TAG_NOTSUPPORTED, subNode.Name));
                }

                //处理节点
                instance = handler.Porcess(subNode, context);

                //判断是否为过滤器
                if (subNode.Name == LogConfiguationTags.TAG_FILTER)
                {
                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace("开始附加日志过滤器'{0}'到日志追加器'{1}'", appender.Name, instance);
                    }

                    //设置日志追加器的过滤器
                    appender.AddFilter((ILogFilter)instance);

                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace("结束附加日志过滤器'{0}'到日志追加器'{1}'", appender.Name, instance);
                    }
                }
                //判断是否为属性
                else if (subNode.Name == LogConfiguationTags.TAG_PROPERTY)
                {
                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace("开始解析日志追加器'{0}'的属性", appender.Name);
                    }

                    //转化为属性
                    property = (PropertyValue)instance;

                    //获得属性
                    propertyInfo = appenderType.GetProperty(property.Name);

                    //判断属性类型是否为日志级别
                    if (typeof(Level) == propertyInfo.PropertyType)
                    {
                        //设置属性值
                        propertyInfo.SetValue(appender, context.Repository.LevelMap[(string)property.Value], null);
                    }
                    else
                    {
                        //设置属性值
                        propertyInfo.SetValue(appender, ObjectUtility.ConvertTo(property.Value, propertyInfo.PropertyType), null);
                    }

                    //输出日志
                    if (LoggingContext.MetaLog.IsTraceEnabled)
                    {
                        LoggingContext.MetaLog.Trace("日志追加器'{0}'的属性'{1}'解析完毕", appender.Name, property.Name);
                    }
                }
            }

            //输出日志
            if (LoggingContext.MetaLog.IsTraceEnabled)
            {
                LoggingContext.MetaLog.Trace("日志追加器'{0}'解析完毕", appender.Name);
            }

            //注册追加器
            context.Repository.RegisterAppender(appender);

            //返回创建的日志追加器
            return appender;
        }
    }
}
